]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st/entry: Forward label-actor to internal ClutterText
authorFlorian Müllner <fmuellner@gnome.org>
Thu, 26 Jun 2025 10:07:07 +0000 (12:07 +0200)
committerMarge Bot <marge-bot@gnome.org>
Fri, 27 Jun 2025 10:47:09 +0000 (10:47 +0000)
The StWidget:label-actor property is a convenient way of setting up an
actor's labelled-by relationship. However on StEntry, it is currently
fairly useless because if the entry is focused, the actual keyboard
focus will be on the internal ClutterText rather than the entry itself,
and orca ignores ancestors in most cases.

Address this by tracking the entry's label-actor property, and replicate
the labelled-by relationship on the internal ClutterText actor.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3179>

src/st/st-entry.c

index 8830d63003ee752656c70a25bb6820fd93988db1..83ce19040f9b8cb80d07d98bc013cd7b9a2bb605 100644 (file)
@@ -122,6 +122,7 @@ G_DECLARE_FINAL_TYPE (StEntryAccessible,
                       StWidgetAccessible)
 
 static void update_hint_relation (StEntry *entry);
+static void update_label_relation (StEntry *entry);
 
 static void
 st_entry_set_property (GObject      *gobject,
@@ -516,6 +517,14 @@ st_entry_allocate (ClutterActor          *actor,
   clutter_actor_allocate (priv->entry, &child_box);
 }
 
+static void
+st_entry_label_actor_changed_cb (StEntry    *entry,
+                                 GParamSpec *pspec,
+                                 gpointer    user_data G_GNUC_UNUSED)
+{
+  update_label_relation (entry);
+}
+
 static void
 clutter_text_reactive_changed_cb (ClutterActor *text,
                                   GParamSpec   *pspec,
@@ -1048,6 +1057,9 @@ st_entry_init (StEntry *entry)
                           priv->entry, "reactive",
                           G_BINDING_DEFAULT);
 
+  g_signal_connect (entry, "notify::label-actor",
+                    G_CALLBACK (st_entry_label_actor_changed_cb), entry);
+
   g_signal_connect(priv->entry, "notify::reactive",
                    G_CALLBACK (clutter_text_reactive_changed_cb), entry);
 
@@ -1528,6 +1540,7 @@ typedef struct _StEntryAccessible
   StWidgetAccessible parent;
 
   AtkObject *current_hint;
+  AtkObject *current_label;
 } StEntryAccessible;
 
 G_DEFINE_FINAL_TYPE (StEntryAccessible, st_entry_accessible, ST_TYPE_WIDGET_ACCESSIBLE)
@@ -1544,6 +1557,7 @@ st_entry_accessible_dispose (GObject *object)
   StEntryAccessible *accessible = ST_ENTRY_ACCESSIBLE (object);
 
   g_clear_object (&accessible->current_hint);
+  g_clear_object (&accessible->current_label);
 
   G_OBJECT_CLASS (st_entry_accessible_parent_class)->dispose (object);
 }
@@ -1656,3 +1670,43 @@ update_hint_relation (StEntry *entry)
                                    accessible);
     }
 }
+
+static void
+update_label_relation (StEntry *entry)
+{
+  StEntryPrivate *priv;
+  AtkObject *accessible;
+  StEntryAccessible *entry_accessible;
+  ClutterActor *label_actor;
+
+  priv = st_entry_get_instance_private (entry);
+
+  accessible = clutter_actor_get_accessible (priv->entry);
+  entry_accessible = ST_ENTRY_ACCESSIBLE (atk_object_get_parent (accessible));
+
+  if (entry_accessible->current_label != NULL)
+    {
+      atk_object_remove_relationship (accessible,
+                                      ATK_RELATION_LABELLED_BY,
+                                      entry_accessible->current_label);
+      atk_object_remove_relationship (entry_accessible->current_label,
+                                      ATK_RELATION_LABEL_FOR,
+                                      accessible);
+      g_clear_object (&entry_accessible->current_label);
+    }
+
+  label_actor = st_widget_get_label_actor (ST_WIDGET (entry));
+
+  if (label_actor != NULL)
+    {
+      g_set_object (&entry_accessible->current_label,
+                    clutter_actor_get_accessible (label_actor));
+
+      atk_object_add_relationship (accessible,
+                                   ATK_RELATION_LABELLED_BY,
+                                   entry_accessible->current_label);
+      atk_object_add_relationship (entry_accessible->current_label,
+                                   ATK_RELATION_LABEL_FOR,
+                                   accessible);
+    }
+}